﻿namespace com.vs.Inventory.BL
{
    using com.vs.DataAccess;
    using com.vs.DataAccess.DO;
    using com.vs.General;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Text;

    public class AllocationHelper
    {
        private static com.vs.Inventory.BL.AllocationHelper _helper = null;
        public bool bCreateTask = true;

        private string adjustInvForAllocationWithoutTask(Session sess, InventoryTransDS itDS)
        {
            InventoryChangeDS item = null;
            List<InventoryChangeDS> arInvChgDS = null;
            string str;
            try
            {
                arInvChgDS = new List<InventoryChangeDS>();
                item = new InventoryChangeDS {
                    WAREHOUSE = itDS.WAREHOUSE,
                    LOCATION = itDS.FROM_LOC,
                    ITEM = itDS.ITEM,
                    COMPANY = itDS.COMPANY,
                    LPN = itDS.FROM_LPN,
                    ATTRIBUTE_NUM = itDS.ATTRIBUTE_NUM,
                    QUANTITY = itDS.QUANTITY,
                    QUANTITY_UM = itDS.QUANTITY_UM,
                    INVENTORY_STS = itDS.INVENTORY_STS,
                    OP_ONHANDQTY = "-",
                    OP_INTRANQTY = "",
                    OP_ALLOCQTY = ""
                };
                arInvChgDS.Add(item);
                item = new InventoryChangeDS {
                    WAREHOUSE = itDS.WAREHOUSE,
                    LOCATION = itDS.TO_LOC,
                    ITEM = itDS.ITEM,
                    COMPANY = itDS.COMPANY,
                    LPN = itDS.TO_LPN,
                    ATTRIBUTE_NUM = itDS.ATTRIBUTE_NUM,
                    QUANTITY = itDS.QUANTITY,
                    QUANTITY_UM = itDS.QUANTITY_UM,
                    INVENTORY_STS = itDS.INVENTORY_STS,
                    OP_ONHANDQTY = "+",
                    OP_INTRANQTY = "",
                    OP_ALLOCQTY = ""
                };
                arInvChgDS.Add(item);
                str = new com.vs.Inventory.BL.InventoryHelper().AdjustInventory(sess, arInvChgDS);
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                str = MessageManager.MSG_GEN_000;
            }
            finally
            {
                item = null;
                arInvChgDS = null;
            }
            return str;
        }

        private string adjustInvForAllocationWithTask(Session sess, InventoryTransDS itDS)
        {
            InventoryChangeDS item = null;
            List<InventoryChangeDS> arInvChgDS = null;
            string str;
            try
            {
                arInvChgDS = new List<InventoryChangeDS>();
                item = new InventoryChangeDS {
                    WAREHOUSE = itDS.WAREHOUSE,
                    LOCATION = itDS.FROM_LOC,
                    ITEM = itDS.ITEM,
                    COMPANY = itDS.COMPANY,
                    LPN = itDS.FROM_LPN,
                    ATTRIBUTE_NUM = itDS.ATTRIBUTE_NUM,
                    QUANTITY = itDS.QUANTITY,
                    QUANTITY_UM = itDS.QUANTITY_UM,
                    INVENTORY_STS = itDS.INVENTORY_STS,
                    OP_ONHANDQTY = "",
                    OP_INTRANQTY = "",
                    OP_ALLOCQTY = "+"
                };
                arInvChgDS.Add(item);
                item = new InventoryChangeDS {
                    WAREHOUSE = itDS.WAREHOUSE,
                    LOCATION = itDS.TO_LOC,
                    ITEM = itDS.ITEM,
                    COMPANY = itDS.COMPANY,
                    LPN = itDS.TO_LPN,
                    ATTRIBUTE_NUM = itDS.ATTRIBUTE_NUM,
                    QUANTITY = itDS.QUANTITY,
                    QUANTITY_UM = itDS.QUANTITY_UM,
                    INVENTORY_STS = itDS.INVENTORY_STS,
                    OP_ONHANDQTY = "",
                    OP_INTRANQTY = "+",
                    OP_ALLOCQTY = ""
                };
                arInvChgDS.Add(item);
                str = new com.vs.Inventory.BL.InventoryHelper().AdjustInventory(sess, arInvChgDS);
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                str = MessageManager.MSG_GEN_000;
            }
            finally
            {
                item = null;
                arInvChgDS = null;
            }
            return str;
        }

        private List<InventoryTransDS> allocateItemByRule(Session sess, InventoryDS ivDS, string stRule, string stToLoc, ref string stError)
        {
            Dictionary<string, int> dictionary = null;
            Dictionary<string, KeyValuePair<string, object>> dcCond = null;
            List<AllocationRuleDetailDO> list = null;
            List<InventoryTransDS> list2 = null;
            List<InventoryTransDS> list3 = null;
            FilterConfigDetailDO modelByPK = null;
            bool flag = false;
            ItemManager manager = null;
            int qUANTITY = 0;
            try
            {
                list2 = new List<InventoryTransDS>();
                manager = new ItemManager();
                dictionary = ItemManager.BreakItemQtyIntoUMs(sess, ivDS.COMPANY, ivDS.ITEM, ivDS.QUANTITY);
                foreach (KeyValuePair<string, int> pair in dictionary)
                {
                    if ((pair.Value + qUANTITY) > 0)
                    {
                        ivDS.QUANTITY = pair.Value + qUANTITY;
                        qUANTITY = 0;
                        dcCond = new Dictionary<string, KeyValuePair<string, object>>();
                        dcCond.Add("ALLOCATION_RULE", new KeyValuePair<string, object>("=", stRule));
                        dcCond.Add("QUANTITY_UM", new KeyValuePair<string, object>("=", pair.Key));
                        list = AllocationRuleDetailDO.GetListByColumns(sess, DictionaryManager.ToList(dcCond), null);
                        if ((list == null) || (list.Count < 1))
                        {
                            stError = MessageManager.MSG_INV_013;
                            return null;
                        }
                        foreach (AllocationRuleDetailDO ldo2 in list)
                        {
                            if (ivDS.QUANTITY <= 0)
                            {
                                break;
                            }
                            flag = ldo2.ROLL_IN_NEXT_UM == "Y";
                            modelByPK = FilterConfigDetailDO.GetModelByPK(sess, ldo2.LOC_SEL_ID);
                            if (modelByPK == null)
                            {
                                stError = MessageManager.MSG_LOC_002;
                                return null;
                            }
                            list3 = this.allocateItemFromLocations(sess, ivDS, modelByPK.FILTER_STATEMENT, stToLoc, ref stError);
                            if (!StringManager.IsEmpty(stError))
                            {
                                HistoryManager.SaveProcessHistory(sess, HistoryManager.ProcessType.iAllocate, HistoryManager.Condition.iFailed, stError, stRule, null, null, null);
                            }
                            if ((list3 == null) || (list3.Count < 1))
                            {
                                HistoryManager.SaveProcessHistory(sess, HistoryManager.ProcessType.iAllocate, HistoryManager.Condition.iInfo, MessageManager.MSG_INV_014, ldo2.SEQUENCE, null, null, null);
                            }
                            else
                            {
                                foreach (InventoryTransDS sds in list3)
                                {
                                    list2.Add(sds);
                                }
                            }
                        }
                        if ((ivDS.QUANTITY > 0) && flag)
                        {
                            qUANTITY = ivDS.QUANTITY;
                        }
                    }
                }
                return list2;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                stError = MessageManager.MSG_GEN_000 + exception.Message;
                return null;
            }
        }

        private List<InventoryTransDS> allocateItemBySpecificLoc(Session sess, InventoryDS ivDS, string stPickLoc, string stToLoc, ref string stError)
        {
            List<InventoryTransDS> list;
            try
            {
                list = this.allocateItemFromLocations(sess, ivDS, new StringBuilder().Append(" SELECT * FROM LOCATION_INVENTORY WHERE LOCATION = @LOCATION AND ITEM = @ITEM ").ToString(), stToLoc, ref stError);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return list;
        }

        private InventoryTransDS allocateItemFromLocation(Session sess, DataRow drInv, InventoryDS ivDS, string stToLoc)
        {
            InventoryTransDS itDS = null;
            int num = 0;
            string str = null;
            int qUANTITY = 0;
            int @int = 0;
            try
            {
                string str2 = DataManager.GetString(drInv, "WAREHOUSE");
                string str3 = DataManager.GetString(drInv, "COMPANY");
                string str4 = DataManager.GetString(drInv, "ITEM");
                string str5 = DataManager.GetString(drInv, "LOCATION");
                string str6 = DataManager.GetString(drInv, "LPN");
                @int = DataManager.GetInt(drInv, "ATTRIBUTE_NUM");
                string str7 = DataManager.GetString(drInv, "INVENTORY_STS");
                num = (DataManager.GetInt(drInv, "ON_HAND_QTY") + DataManager.GetInt(drInv, "IN_TRANSIT_QTY")) - DataManager.GetInt(drInv, "ALLOCATED_QTY");
                if (num > ivDS.QUANTITY)
                {
                    qUANTITY = ivDS.QUANTITY;
                    ivDS.QUANTITY = 0;
                }
                else
                {
                    qUANTITY = num;
                    ivDS.QUANTITY -= qUANTITY;
                }
                itDS = new InventoryTransDS {
                    WAREHOUSE = str2,
                    COMPANY = str3,
                    ITEM = str4,
                    FROM_LOC = str5,
                    FROM_LPN = str6,
                    TO_LOC = stToLoc,
                    TO_LPN = null,
                    ATTRIBUTE_NUM = @int,
                    QUANTITY = qUANTITY,
                    QUANTITY_UM = ivDS.QUANTITY_UM,
                    INVENTORY_STS = ivDS.INVENTORY_STS
                };
                if (this.bCreateTask)
                {
                    str = this.adjustInvForAllocationWithTask(sess, itDS);
                }
                else
                {
                    str = this.adjustInvForAllocationWithoutTask(sess, itDS);
                }
                if (!StringManager.IsEmpty(str))
                {
                    return null;
                }
                return itDS;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                return null;
            }
        }

        private List<InventoryTransDS> allocateItemFromLocations(Session sess, InventoryDS ivDS, string stSQL, string stToLoc, ref string stError)
        {
            List<InventoryTransDS> list = null;
            DataHelper helper = null;
            DataTable table = null;
            InventoryTransDS item = null;
            List<InventoryTransDS> list2;
            try
            {
                LockManager.GetInventoryLock(sess, ivDS.ITEM, ivDS.COMPANY, ivDS.WAREHOUSE);
                helper = new DataHelper(sess);
                table = helper.GetTable(CommandType.Text, stSQL, new IDataParameter[] { DataHelper.BuildParameter(sess, "@COMPANY", ivDS.COMPANY), DataHelper.BuildParameter(sess, "@ITEM", ivDS.ITEM), DataHelper.BuildParameter(sess, "@ATTRIBUTE1", ivDS.ATTRIBUTE1), DataHelper.BuildParameter(sess, "@ATTRIBUTE2", ivDS.ATTRIBUTE2), DataHelper.BuildParameter(sess, "@ATTRIBUTE3", ivDS.ATTRIBUTE3), DataHelper.BuildParameter(sess, "@ATTRIBUTE4", ivDS.ATTRIBUTE4), DataHelper.BuildParameter(sess, "@ATTRIBUTE5", ivDS.ATTRIBUTE5), DataHelper.BuildParameter(sess, "@ATTRIBUTE6", ivDS.ATTRIBUTE6), DataHelper.BuildParameter(sess, "@ATTRIBUTE7", ivDS.ATTRIBUTE7), DataHelper.BuildParameter(sess, "@ATTRIBUTE8", ivDS.ATTRIBUTE8), DataHelper.BuildParameter(sess, "@PICK_LOC", ivDS.LOCATION), DataHelper.BuildParameter(sess, "@INVENTORY_STS", ivDS.INVENTORY_STS) });
                if (DataManager.IsEmpty(table))
                {
                    stError = MessageManager.MSG_INV_011;
                    return null;
                }
                list = new List<InventoryTransDS>();
                foreach (DataRow row in table.Rows)
                {
                    if (ivDS.QUANTITY <= 0)
                    {
                        break;
                    }
                    item = this.allocateItemFromLocation(sess, row, ivDS, stToLoc);
                    if (item.QUANTITY > 0)
                    {
                        list.Add(item);
                    }
                }
                list2 = list;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                stError = MessageManager.MSG_GEN_000 + exception.Message;
                list2 = null;
            }
            finally
            {
                if (helper != null)
                {
                    helper.Dispose();
                }
                LockManager.ReleaseInventoryLock(sess, ivDS.ITEM, ivDS.COMPANY, ivDS.WAREHOUSE);
            }
            return list2;
        }

        public string AllocateShipment(Session sess, ShipmentHeaderDO shDO)
        {
            List<ShipmentDetailDO> list = null;
            string str = null;
            try
            {
                list = ShipmentDetailDO.GetListByColumn(sess, "INTERNAL_SHIPMENT_NUM", shDO.INTERNAL_SHIPMENT_NUM);
                if (list.Count < 1)
                {
                    return MessageManager.MSG_SHP_001;
                }
                foreach (ShipmentDetailDO ldo in list)
                {
                    str = this.AllocateShipmentLine(sess, ldo, ldo.ALLOCATION_RULE, false);
                    if (!StringManager.IsEmpty(str))
                    {
                        HistoryManager.SaveProcessHistory(sess, HistoryManager.ProcessType.iAllocate, HistoryManager.Condition.iFailed, str, ldo.SHIPMENT_ID, ldo.INTERNAL_SHIPMENT_LINE_NUM, null, null);
                    }
                }
                return null;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                str = MessageManager.MSG_GEN_000 + exception.Message;
                return null;
            }
        }

        public string AllocateShipmentLine(Session sess, ShipmentDetailDO sdDO, string stRule, bool bIsReplenish)
        {
            string str = null;
            List<InventoryTransDS> list = null;
            InventoryDS ivDS = null;
            Dictionary<string, object> dcData = null;
            ShipmentAllocRequestDO tdo = null;
            ItemManager instance = null;
            ItemUnitOfMeasureDO edo = null;
            string stQtyUM = null;
            int qUANTITY = 0;
            int num2 = 0;
            string stError = null;
            try
            {
                str = sdDO.DOCK_LOC;
                if (StringManager.IsEmpty(str))
                {
                    str = "SHIP-01";
                }
                if ((sdDO.REQUEST_QTY - sdDO.TOTAL_QTY) <= 0)
                {
                    return MessageManager.MSG_WAV_014;
                }
                ivDS = new InventoryDS {
                    WAREHOUSE = sdDO.WAREHOUSE,
                    COMPANY = sdDO.COMPANY,
                    ITEM = sdDO.ITEM,
                    QUANTITY = sdDO.REQUEST_QTY - sdDO.TOTAL_QTY,
                    QUANTITY_UM = sdDO.QUANTITY_UM
                };
                if (StringManager.Equals("Y", sdDO.ATTRIBUTE_TRACK))
                {
                    ivDS.ATTRIBUTE1 = sdDO.ATTRIBUTE1;
                    ivDS.ATTRIBUTE2 = sdDO.ATTRIBUTE2;
                    ivDS.ATTRIBUTE3 = sdDO.ATTRIBUTE3;
                    ivDS.ATTRIBUTE4 = sdDO.ATTRIBUTE4;
                    ivDS.ATTRIBUTE5 = sdDO.ATTRIBUTE5;
                    ivDS.ATTRIBUTE6 = sdDO.ATTRIBUTE6;
                    ivDS.ATTRIBUTE7 = sdDO.ATTRIBUTE7;
                    ivDS.ATTRIBUTE8 = sdDO.ATTRIBUTE8;
                }
                ivDS.INVENTORY_STS = sdDO.INVENTORY_STS;
                list = new List<InventoryTransDS>();
                list = this.allocateItemByRule(sess, ivDS, stRule, str, ref stError);
                if ((list == null) || (list.Count < 1))
                {
                    HistoryManager.SaveProcessHistory(sess, HistoryManager.ProcessType.iAllocate, HistoryManager.Condition.iFailed, MessageManager.MSG_WAV_007, sdDO.INTERNAL_WAVE_NUM, sdDO.SHIPMENT_ID, sdDO.INTERNAL_SHIPMENT_LINE_NUM, stRule);
                    return null;
                }
                instance = ItemManager.GetInstance();
                foreach (InventoryTransDS sds in list)
                {
                    bool flag;
                    tdo = new ShipmentAllocRequestDO {
                        WAREHOUSE = sds.WAREHOUSE,
                        COMPANY = sds.COMPANY,
                        ITEM = sds.ITEM,
                        FROM_LOC = sds.FROM_LOC,
                        TO_LOC = sds.TO_LOC,
                        FROM_LPN = sds.FROM_LPN,
                        ATTRIBUTE_NUM = sds.ATTRIBUTE_NUM,
                        ALLOCATED_QTY = sds.QUANTITY,
                        QUANTITY_UM = sds.QUANTITY_UM,
                        INVENTORY_STS = sds.INVENTORY_STS,
                        TASK_CREATED = this.bCreateTask ? "Y" : "N",
                        ITEM_DESC = sdDO.ITEM_DESC,
                        INTERNAL_SHIPMENT_NUM = sdDO.INTERNAL_SHIPMENT_NUM,
                        INTERNAL_SHIPMENT_LINE_NUM = sdDO.INTERNAL_SHIPMENT_LINE_NUM,
                        SHIPMENT_ID = sdDO.SHIPMENT_ID,
                        SHIPMENT_TYPE = sdDO.SHIPMENT_TYPE,
                        REQUESTED_QTY = sdDO.REQUEST_QTY,
                        INTERNAL_WAVE_NUM = sdDO.INTERNAL_WAVE_NUM,
                        REPLENISHMENT_REQD = bIsReplenish ? "Y" : "N"
                    };
                    stQtyUM = sds.QUANTITY_UM;
                    qUANTITY = sds.QUANTITY;
                    goto Label_039B;
                Label_0314:
                    edo = instance.GetParentUM(sess, sds.ITEM, sds.COMPANY, stQtyUM);
                    if (((edo != null) && (sds.QUANTITY >= edo.CONVERSION_QTY)) && ((sds.QUANTITY % edo.CONVERSION_QTY) == 0))
                    {
                        stQtyUM = edo.QUANTITY_UM;
                        qUANTITY = sds.QUANTITY / edo.CONVERSION_QTY;
                    }
                    else
                    {
                        goto Label_03A3;
                    }
                Label_039B:
                    flag = true;
                    goto Label_0314;
                Label_03A3:
                    tdo.CONVERTED_ALLOC_QTY = qUANTITY;
                    tdo.CONVERTED_QTY_UM = stQtyUM;
                    tdo.Insert(sess);
                    num2 += sds.QUANTITY;
                }
                dcData = new Dictionary<string, object>();
                dcData.Add("TOTAL_QTY", sdDO.TOTAL_QTY + num2);
                sdDO.Update(sess, dcData);
                return null;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                HistoryManager.SaveProcessHistory(sess, HistoryManager.ProcessType.iTechnical, HistoryManager.Condition.iError, MessageManager.MSG_GEN_000 + exception.Message);
                stError = MessageManager.MSG_GEN_000 + exception.Message;
                return null;
            }
        }

        public string AllocateWave(Session sess, int iWaveNum)
        {
            string str = null;
            Dictionary<string, object> dcData = null;
            List<ShipmentHeaderDO> list = null;
            try
            {
                list = ShipmentHeaderDO.GetListByColumn(sess, "INTERNAL_WAVE_NUM", iWaveNum);
                if ((list == null) || (list.Count < 1))
                {
                    return MessageManager.MSG_WAV_004;
                }
                foreach (ShipmentHeaderDO rdo in list)
                {
                    str = this.AllocateShipment(sess, rdo);
                    if (!StringManager.IsEmpty(str))
                    {
                        dcData = new Dictionary<string, object>();
                        dcData.Add("LEADING_STS", 100);
                        dcData.Add("TRAILING_STS", 100);
                        dcData.Add("REJECTION_NOTE", str);
                        rdo.Update(sess, dcData);
                    }
                }
                return null;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                return (MessageManager.MSG_GEN_000 + exception.Message);
            }
        }

        public string DeallocateShipment(Session sess, int iShpNum)
        {
            DataHelper helper = null;
            try
            {
                helper = new DataHelper(sess);
                return helper.GetString(CommandType.StoredProcedure, "WAV_DeallocShipment", new IDataParameter[] { DataHelper.BuildParameter(sess, "@INTERNAL_SHIPMENT_NUM", iShpNum) });
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                return (MessageManager.MSG_GEN_000 + exception.Message);
            }
        }

        public string DeallocateShpLine(Session sess, int iShpLnNum)
        {
            try
            {
                return null;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                return MessageManager.MSG_GEN_000;
            }
        }

        private List<string> getDefaultAllocationRule(Session sess)
        {
            return new List<string> { "SELECT LOCATION FROM LOCATION WHERE LOCATION_STS <> 'Empty'" };
        }

        public static com.vs.Inventory.BL.AllocationHelper GetInstance()
        {
            if (_helper == null)
            {
                _helper = new com.vs.Inventory.BL.AllocationHelper();
            }
            return _helper;
        }
    }
}

